package com.kingsoft.miot.bridge.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.kingsoft.miot.bridge.common.CommonResult;
import com.kingsoft.miot.bridge.controller.resp.HotelInfoDetailResp;
import com.kingsoft.miot.bridge.controller.resp.HotelInfoResp;
import com.kingsoft.miot.bridge.controller.resp.PageResult;
import com.kingsoft.miot.bridge.dao.AreaInfoDao;
import com.kingsoft.miot.bridge.dao.AuthUnitIdInfoDao;
import com.kingsoft.miot.bridge.dao.HotelInfoDao;
import com.kingsoft.miot.bridge.dao.PageBean;
import com.kingsoft.miot.bridge.exception.CommonException;
import com.kingsoft.miot.bridge.pojo.ServiceAuth;
import com.kingsoft.miot.bridge.pojo.SignAndVerify;
import com.kingsoft.miot.bridge.pojo.account.AuthUnitIdInfo;
import com.kingsoft.miot.bridge.pojo.hotel.HotelInfo;
import com.kingsoft.miot.bridge.pojo.hotel.HotelUris;
import com.kingsoft.miot.bridge.service.HotelService;
import com.kingsoft.miot.bridge.utils.HttpUtils;

/**
 * 酒店服务
 * 
 * @author HUJIANQING
 *
 */
@Service
public class HotelServiceImpl extends BaseServiceImpl implements HotelService {

	private static final Logger LOGGER = LoggerFactory.getLogger(HotelServiceImpl.class);

	// 服务商提供参数
	@Autowired
	private ServiceAuth serviceAuth;
	// hotel 接口
	@Autowired
	private HotelUris hotelUris;
	// 酒店详细信息接口
	@Autowired
	private HotelInfoDao hotelInfoDao;
//	// 房间信息基本接口
//	@Autowired
//	private RoomInfoDao roomInfoDao;
	// 区域服务
	@Autowired
	private AreaInfoDao areaInfoDao;
	// 认证授权服务
	@Autowired
	private AuthUnitIdInfoDao authUnitIdInfoDao;

	/**
	 * 新增酒店
	 */
	@Override
	@Transactional(propagation = Propagation.SUPPORTS)
	public void insertOne(HotelInfo hotel) {
		// 1. 验证区域是否存在
//		if (areaInfoDao.getByAreaInfoName(hotel.getArea_info_name()) == null) {
//			return;
//		}
		try {
			// 2. 分配新的auth unit id
//			AuthUnitIdInfo auth_unit_id = authUnitIdInfoDao.getAuthUnitIdWithRandom();
//			hotel.setAuth_unit_id(auth_unit_id.getAuth_unit_id_info_str());
			// 3.新增酒店
			hotelInfoDao.insertOne(hotel);
		} catch (Exception e) {
			throw new RuntimeException("新增酒店失败");
		}
	}

	/**
	 * 分页获取
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public PageResult<HotelInfoResp> findHotelByPage(int currentPage, int pageSize) {
		// 设置分页信息，分别是当前页数和每页显示的总记录数【记住：必须在mapper接口中的方法执行之前设置该分页信息】
		PageHelper.startPage(currentPage, pageSize);
		// 暂时查询总记录数
		List<HotelInfo> allHotel = hotelInfoDao.findAll(); // 全部商品
		int countNums = allHotel.size(); // 总记录数
		PageBean<HotelInfo> pageData = new PageBean<>(currentPage, pageSize, countNums);
		pageData.setItems(allHotel);
		PageResult<HotelInfoResp> pageResult = new PageResult<HotelInfoResp>();
		pageResult.setCurrent_page(currentPage);
		pageResult.setSize(pageSize);
		pageResult.setTotal_count(countNums);
		pageResult.setTotal_pages(pageData.getTotalPage());
		// 起始也
		int start = (currentPage - 1) * pageSize >= allHotel.size() ? (allHotel.size() / pageSize) * pageSize
				: (currentPage - 1) * pageSize;
		// 最终页
		int end = currentPage * pageSize >= allHotel.size() ? allHotel.size() : currentPage * pageSize;
		List<HotelInfo> subList = allHotel.subList(start, end);
		List<HotelInfoResp> retList = new ArrayList<>();
		// 设置返回数据 需要改进 bean utils
		for (HotelInfo item : subList) {
			HotelInfoResp resp = new HotelInfoResp();
			fillToHotelInfoResp(item, resp);
			// 1. 设置设备总数 需要查询该酒店相关的所有设备
			resp.setDevices_total_num(2000);
			// 2. 设置在线设备总数 需要查询该酒店相关的所有在线设备
			resp.setDevices_online_num(700);
			retList.add(resp);
		}
		pageResult.setItem_list(retList);
		return pageResult;
	}

	/**
	 * 新增room 通过hotel id
	 */
//	@Override
//	public void addHotelRoom(RoomInfo roomInfo) {
//		if (roomInfo == null) {
//			throw new RuntimeException("roomInfo 不能为空");
//		}
//		HotelInfo hotelInfo = hotelInfoDao.getById(roomInfo.getHotel_info_id());
//		long auth_unit_id = hotelInfo.getAuth_unit_id();
//		// 1. 生成control_unit_id
//		String control_unit_id = getControlUnitId(auth_unit_id + "");
//		String name = UUID.randomUUID().toString() + System.currentTimeMillis();
//		// 2. get home id
//		int homeId = getHomeId(control_unit_id, name);
//		// 3. 获取room id
//		int roomId = getRoomId(control_unit_id + "", homeId + "", name);
//		// 4. 插入room_info 基本信息
//		if (roomId == -1) {
//			LOGGER.error("roomid 分配失败!");
//			throw new RuntimeException("roomId 分配失败!");
//		}
//		roomInfo.setHotel_info_id(hotelInfo.getHotel_info_id());
//		roomInfo.setAuth_unit_id(auth_unit_id);
//		roomInfoDao.insertOne(roomInfo);
//	}

	/**
	 * 获取 control unit id
	 * 
	 * @param authUnitId
	 * @return
	 */
	public String getControlUnitId(String authUnitId) {
		String method = "POST";
		String url = serviceAuth.getServiceUrl() + hotelUris.getGetControlUnitIdUri();
		JSONObject dataValueJson = new JSONObject();
		String nonceStr = System.currentTimeMillis() + "";
//		List<NameValuePair> params = createParams(groupId, authUnitId, privateKey, method, uri, nonceStr,
//				dataValueJson.toString());
		// 填充groupId 和 AuthUnitId
		List<NameValuePair> params = new LinkedList<>();
		params.add(new BasicNameValuePair("_nonce", nonceStr));
		params.add(new BasicNameValuePair("_groupId", serviceAuth.getGroupId()));
		params.add(new BasicNameValuePair("_authUnitId", authUnitId + ""));
		params.add(new BasicNameValuePair("_data", dataValueJson.toJSONString()));
		// ECDSA 离线验证
		SignAndVerify signAndVerify = verify(method, hotelUris.getGetControlUnitIdUri(), dataValueJson.toJSONString(),
				nonceStr, serviceAuth.getPublicKey(), serviceAuth.getPrivateKey());
		params.add(new BasicNameValuePair("_signature", signAndVerify.getSign()));
		String postResult = HttpUtils.sendPost(url, params);
		System.out.println(postResult);
		JSONObject jsonObject = new JSONObject();
		Map<String, Object> map = jsonObject.parseObject(postResult, Map.class);
		Object object = map.get("data");
		Map<String, Object> map2 = jsonObject.parseObject(object.toString(), Map.class);
		if (map2 == null || map2.size() <= 0) {
			throw new RuntimeException("获取control unit id 失败");
		}
		return (String) map2.get("controlUnitId");
	}

	/**
	 * 通过control unit id 获取HomeId
	 * 
	 * @param controlUnitId
	 * @return
	 */
	public int getHomeId(String controlUnitId, String name) {
		String result = "";
		String method = "POST";
		String url = serviceAuth.getServiceUrl() + hotelUris.getAddHomeUri();
		JSONObject dataMap = new JSONObject();
		try {
			dataMap.put("controlUnitId", controlUnitId);
			// 注意 家庭名称必须不一样 目前新建room时需要每次都新建家庭 (需要修改)
			dataMap.put("name", name);
			String value = dataMap.toJSONString();
			// 时间戳
			String nonceStr = System.currentTimeMillis() + "";
			List<NameValuePair> params = new ArrayList<>();
			// 填充groupId 和 AuthUnitId
			String groupId = serviceAuth.getGroupId();
			params.add(new BasicNameValuePair("_groupId", groupId));
			params.add(new BasicNameValuePair("_nonce", nonceStr));
			params.add(new BasicNameValuePair("_data", value));
			// ECDSA 离线验证
			SignAndVerify signAndVerify = verify(method, hotelUris.getAddHomeUri(), value, nonceStr,
					serviceAuth.getPublicKey(), serviceAuth.getPrivateKey());
			// 待参考
//			if (!signAndVerify.isVerify()) {
//				LOGGER.error("离线验证失败。");
//				return null;
//			}
			params.add(new BasicNameValuePair("_signature", signAndVerify.getSign()));
			result = HttpUtils.sendPost(url, params);
		} catch (Exception e) {
			LOGGER.error("测试出现未知异常。");
		}

		// 返回结果不为空
		if (!StringUtils.isBlank(result)) {
			JSONObject jsonObject = new JSONObject();
			Map<String, Object> map = jsonObject.parseObject(result, Map.class);
			Object object = map.get("data");
			Map<String, Object> map2 = jsonObject.parseObject(object.toString(), Map.class);
			Object obj = map2.get("id");
			if (obj == null) {
				return -1;
			}
			return Integer.valueOf(obj.toString());
		}
		// 返回
		return -1;
	}

	/**
	 * 获取room id
	 * 
	 * @param controlUnitId
	 * @param homeId
	 * @param name
	 * @return
	 */
	@Transactional(propagation = Propagation.SUPPORTS)
	public int getRoomId(String controlUnitId, String homeId, String name) {
		String result = "";
		String method = "POST";
		String url = serviceAuth.getServiceUrl() + hotelUris.getAddroomUri();
		JSONObject dataMap = new JSONObject();
		try {
			dataMap.put("controlUnitId", controlUnitId);
			dataMap.put("homeId", homeId);
			dataMap.put("name", name);
			String value = dataMap.toJSONString();
			// 请求时间戳
			String nonceStr = System.currentTimeMillis() + "";
			List<NameValuePair> params = new ArrayList<>();
			// 填充groupId 和 AuthUnitId
			String groupId = serviceAuth.getGroupId();
			params.add(new BasicNameValuePair("_groupId", groupId));
			params.add(new BasicNameValuePair("_nonce", nonceStr));
			params.add(new BasicNameValuePair("_data", value));
			// ECDSA 离线验证
			SignAndVerify signAndVerify = verify(method, hotelUris.getAddHomeUri(), value, nonceStr,
					serviceAuth.getPublicKey(), serviceAuth.getPrivateKey());
			// 待参考
//			if (!signAndVerify.isVerify()) {
//				LOGGER.error("离线验证失败。");
//				return null;
//			}
			params.add(new BasicNameValuePair("_signature", signAndVerify.getSign()));
			result = HttpUtils.sendPost(url, params);
		} catch (Exception e) {
			LOGGER.error("测试出现未知异常。");
		}

		// 返回结果不为空
		if (!StringUtils.isBlank(result)) {
			JSONObject jsonObject = new JSONObject();
			Map<String, Object> map = jsonObject.parseObject(result, Map.class);
			Object object = map.get("data");
			Map<String, Object> map2 = jsonObject.parseObject(object.toString(), Map.class);
			Object obj = map2.get("id");
			if (obj == null) {
				return -1;
			}
			return Integer.valueOf(obj.toString());
		}
		// 返回
		return -1;

	}

	/**
	 * 通过hotel id获取hotelinfo
	 */
	@Override
	public HotelInfoDetailResp getHotelInfoDetailResp(int id) {
		HotelInfoDetailResp resp = null;
		try {
			HotelInfo hotelInfo = hotelInfoDao.getById(id);
			if (hotelInfo == null) {
				return null;
			}
			resp = new HotelInfoDetailResp();
			fillToHotelInfoDetailResp(hotelInfo, resp);
			// 1. 设置设备总数 这里需要关联查询
			resp.setDevices_online_num(200);
			// 2. 设置设备在线总数 这里需要关联查询
			resp.setDevices_total_num(1000);
			short status = hotelInfo.getHotel_info_use_status();
			Map<String, Object> hashMap = new HashMap<>();
			if (0 == status) {
				hashMap.put("name", "已停用");
				hashMap.put("value", 0);
			} else if (1 == status) {
				hashMap.put("name", "已启用");
				hashMap.put("value", 1);
			} else {
				throw new CommonException("获取酒店详细信息失败。");
			}
			resp.setStatus(hashMap);
		} catch (Exception e) {
			throw new CommonException("获取数据失败");
		}
		return resp;
	}

	/**
	 * 通过id暂停hotel
	 * 
	 * 0: 酒店停用 1: 酒店使用中
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public int pauseOrStartHotelById(int hotel_id, short status) {
		// 1.查询是否存在hotel
		HotelInfo hotelInfo = hotelInfoDao.getById(hotel_id);
		if (hotelInfo == null) {
			LOGGER.error("暂停酒店使用失败");
			return -1;
		}
		// 2. 暂停使用
		try {
			hotelInfo.setHotel_info_use_status(status);
			hotelInfoDao.update(hotelInfo);
			return 1;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 更新酒店 成返回1 失败返回-1
	 */
	@Transactional(propagation = Propagation.SUPPORTS)
	@Override
	public int updateHotelInfoById(/* HashMap<String,Object> reqMap **/ HotelInfo hotelInfo) {
		// 1.查询是否存在该数据
		HotelInfo hotelInfoTmp = hotelInfoDao.getById(hotelInfo.getHotel_info_id());
		if (hotelInfoTmp == null) {
			LOGGER.info("更新失败，不存在该条数据。");
			return -1;
		}
		try {
			// 2.更新数据
			hotelInfoDao.update(hotelInfo);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return 1;
	}

	/**
	 * 删除管理人员
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public int deleteManager(int hotel_id, List<String> managerList) {
		try {
			HotelInfo hotelInfo = hotelInfoDao.getById(hotel_id);
			String managerStr = hotelInfo.getHotel_info_managers();
			List<String> oldList = JSON.parseObject(managerStr, List.class);
			// 删除列表中的管理者 如果有多个的话
			oldList.removeAll(managerList);
			hotelInfo.setHotel_info_managers(JSON.toJSONString(oldList));
			updateHotelInfoById(hotelInfo);
		} catch (Exception e) {
			LOGGER.error("删除酒店管理人员失败失败");
			return -1;
		}
		return 1;
	}

	/**
	 * 通过auth unit id 批量查询酒店
	 */
	@Override
	public List<HotelInfo> getByAuthUnitIdList(Set<Integer> authUnitIdList) {
		List<HotelInfo> hotelList = null;
		try {
			hotelList = hotelInfoDao.getByAuthUnitIdList(authUnitIdList);
		} catch (Exception e) {
			throw new CommonException(e);
		}
		return hotelList;
	}

	/**
	 * 通过 hotel id 批量查询酒店
	 */
	@Override
	public List<HotelInfo> getByHotelIdList(Set<Integer> hotelIdList) {
		List<HotelInfo> hotelList = null;
		try {
			hotelList = hotelInfoDao.getByHotelIdList(hotelIdList);
		} catch (Exception e) {
			throw new CommonException(e);
		}
		return hotelList;
	}

	/**
	 * 查询所有的hotel info
	 */
	@Transactional(propagation = Propagation.SUPPORTS)
	@Override
	public List<HotelInfo> findAll() {
		try {
			return hotelInfoDao.findAll();
		} catch (Exception e) {
			LOGGER.error("查询所有的酒店。");
			throw new CommonException(e);
		}
	}

	/**
	 * 填充数据到 hotelInfoResp
	 * 
	 * @param dest
	 * @param target
	 */
	private void fillToHotelInfoResp(HotelInfo dest, HotelInfoResp target) {
		// 酒店状态
		if(dest == null){
			return;
		}
		short statusNum = dest.getHotel_info_use_status();
		Map<String, Object> dataMap = new HashMap<>();
		if (statusNum == 1) {
			dataMap.put("name", "使用中");
			dataMap.put("value", 1);
		} else if (statusNum == 0) {
			dataMap.put("name", "未使用");
			dataMap.put("value", 0);
		} else {
			dataMap.put("name", "已停用");
			dataMap.put("value", -1);
		}
		// 设置酒店状态
		target.setStatus(dataMap);
		target.setId(dest.getHotel_info_id());
		target.setName(dest.getHotel_info_name());
		target.setHouse_total_num(dest.getHotel_info_house_total_num());
		target.setCreate_time(dest.getHotel_info_create().getTime());
	}

	/**
	 * 填充数据到HotelInfoDetailResp
	 * 
	 * @param dest
	 * @param target
	 */
	@SuppressWarnings("unchecked")
	private void fillToHotelInfoDetailResp(HotelInfo dest, HotelInfoDetailResp target) {
		target.setId(dest.getHotel_info_id());
		target.setCreate_time(dest.getHotel_info_create().getTime());
		target.setFloors_total_num(dest.getHotel_info_floors_total_num());
		target.setHouse_total_num(dest.getHotel_info_house_total_num());
		target.setManager_list(JSON
				.parseObject(dest.getHotel_info_managers() == null ? "" : dest.getHotel_info_managers(), List.class));
		target.setName(dest.getHotel_info_name());
	}

	/**
	 * 通过名称获取hotel info
	 */
	@Override
	public HotelInfo getHotelInfoByName(String name) {
		HotelInfo hotelInfo = null;
		try {
			hotelInfo = hotelInfoDao.getByName(name);
			return hotelInfo;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 为酒店添加管理员
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public int addHotelManager(int hotel_id, String email) {
		// 1. 查询是否存在酒店
		HotelInfo hotelInfo = hotelInfoDao.getById(hotel_id);
		if (hotelInfo == null) {
			return -1;
		}
		try {
			// 2. 添加新的管理员
			String managers = hotelInfo.getHotel_info_managers();
			List<String> emailList = null;
			if (StringUtils.isBlank(managers)) {
				emailList = new ArrayList<>();
			} else {
				emailList = JSON.parseObject(managers, List.class);
			}
			HashSet<String> managerSet = new HashSet<>();
			managerSet.addAll(emailList);
			managerSet.add(email);
			hotelInfo.setHotel_info_managers(JSON.toJSONString(managerSet));
			// 3. 更新改管理员数据
			hotelInfoDao.update(hotelInfo);
		} catch (Exception e) {
			throw new CommonException(e);
		}
		return 1;
	}

	/**
	 * 通过id获取hotel Info
	 */
	@Override
	public HotelInfo getById(int hotelId) {
		try {
			return hotelInfoDao.getById(hotelId);
		} catch (Exception e) {
			throw new CommonException(e);
		}
	}

	/**
	 * 通过authunit id 获取数据
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public PageResult<HotelInfoResp> getByAuthUnitId(int authUnitId) {
		try {
			HotelInfo hotelInfo = hotelInfoDao.getByAuthUnitId(authUnitId);
			PageResult<HotelInfoResp> pageResult = new PageResult<HotelInfoResp>();
			pageResult.setCurrent_page(1);
			pageResult.setSize(1);
			pageResult.setTotal_count(1);
			pageResult.setTotal_pages(1);
			HotelInfoResp resp = new HotelInfoResp();
			if(hotelInfo == null) {
				pageResult.setItem_list(new ArrayList<>());
				return pageResult;
			}
			fillToHotelInfoResp(hotelInfo, resp);
			// 1. 设置设备总数 需要查询该酒店相关的所有设备
			resp.setDevices_total_num(2000);
			// 2. 设置在线设备总数 需要查询该酒店相关的所有在线设备
			resp.setDevices_online_num(700);
			List<HotelInfoResp> retList = new ArrayList<>();
			retList.add(resp);
			pageResult.setItem_list(retList);
			return pageResult;
		} catch (Exception e) {
			throw new CommonException(e);
		}
	}
}
